<?php

use Workerman\Worker;
use Workerman\Lib\Timer;
use Channel\Server;
use WSRoute\Provider as RouteProvider;
use Connect\ConnectManager;
use Response\JsonResponse;

require_once "./vendor/autoload.php";

$route = new RouteProvider();
$route->boot();

$connectManager = ConnectManager::getInstance();

// 初始化一个Channel服务端
$channel_server = new Server('0.0.0.0', 2206);

$websocketServer = new Worker('websocket://0.0.0.0:31675');

$websocketServer->count = 1;

$websocketServer->onWorkerStart = function ($worker) use ($connectManager) {
    // Channel客户端连接到Channel服务端
    Channel\Client::connect('127.0.0.1', 2206);
    // 以自己的进程id为事件名称
    $event_name = $worker->id;

    // 订阅广播事件,收到广播事件后向当前进程内所有客户端连接发送广播数据
    Channel\Client::on('broadcast', function($event_data) use ($worker, $connectManager) {
        $message = $event_data;
        $connections = $connectManager->getClients($worker->id);

        foreach($connections as $connection)
        {
            $connection->send(json_encode($message));
        }
    });

    Timer::add(5, function() use ($worker, $connectManager) {

        // 进程启动后设置一个每秒运行一次的定时器
        $time_now = time();
        foreach($connectManager->getClients($worker->id) as $connection) {
            // 有可能该connection还没收到过消息，则lastMessageTime设置为当前时间
            if (empty($connection->lastMessageTime)) {
                $connection->lastMessageTime = $time_now;
                continue;
            }
            // 上次通讯时间间隔大于心跳间隔，则认为客户端已经下线，关闭连接
            if ($time_now - $connection->lastMessageTime > 15) {
                $connection->close();
            }
        }
    });
};

$websocketServer->onConnect = function ($connection) use ($websocketServer, $connectManager) {
    $connectManager->addClient($websocketServer->id, $connection->id, $connection);
};

$websocketServer->onMessage = function ($connection, $data) use ($route, $websocketServer) {

    try {
        $data = json_decode($data, true);
    } catch (\Exception $e) {
        $response = new JsonResponse(500, json_last_error(), json_last_error_msg());
        $response->send($connection);
    }

    if (!isset($data['method']) || !isset($data['route']) || !isset($data['request'])) {
        $response = new JsonResponse(400, 'Bad Request', 'request must require method,route,request');
    }

    $response = $route->parse($data['method'], $data['route'], $data['request'], [
        'connection' => $connection,
        'worker' => $websocketServer
    ]);
};

$websocketServer->onClose = function ($connection) use ($websocketServer, $connectManager) {
    $connectManager->removeClient($websocketServer->id, $connection->id);
};

// 用来处理http请求，向任意客户端推送数据，需要传workerID和connectionID
$http_worker = new Worker('http://0.0.0.0:4237');
$http_worker->name = 'publisher';
$http_worker->onWorkerStart = function()
{
    Channel\Client::connect('127.0.0.1', 2206);
};
$http_worker->onMessage = function($connection, $data) use ($route)
{
    $response = $route->parse(strtolower($_SERVER['REQUEST_METHOD']), $_SERVER['REQUEST_URI'], json_decode($_POST['request']));
    $response->send($connection);
};

// 运行worker
Worker::runAll();
